/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.composite.editpart;

import java.util.Iterator;
import java.util.StringTokenizer;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.Stereotype;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.NodeNameDisplayEditPart;
import com.cea.papyrus.core.figures.StringFigure;
import com.cea.papyrus.core.helper.ModelerHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.Di2Factory;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Property;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;
import com.cea.papyrus.umlutils.ICustomAppearence;

/**
 * Controler of name edit parts for Ports.
 */
public class PortNameEditPart extends NodeNameDisplayEditPart{

	/** Port for which the name has to be displayed */
	private org.eclipse.uml2.uml.Port port;

	/**
	 * Creates a new PortNameEditPart
	 * @param graphnode the graph node displaying the name of the port
	 * @param modelManager the model manager associated to the model
	 */
	public PortNameEditPart(GraphNode graphnode, ModelManager modelManager) {
		super(graphnode,modelManager);
		Debug.debug(this,"create PortNameEditPart("+ graphnode+")",channel);
		if ((GraphNode)graphnode.getSemanticParent()==null){
			Debug.error(this, "PortEditPart is not associated to a port", channel);
		} else {
			port=(org.eclipse.uml2.uml.Port)((Uml1SemanticModelBridge)((GraphNode)graphnode.getSemanticParent()).getSemanticModel()).getElement();
		}
	}

	/**
	 * Creates a new PortNameEditPart
	 * @param graphnode the graph node displaying the name of the port
	 * @param element 
	 * @param modelManager the model manager associated to the model 
	 */
	public PortNameEditPart(GraphNode graphnode, org.eclipse.uml2.uml.Element element, ModelManager modelManager) {
		super(graphnode,modelManager);
		Debug.debug(this,"create PortNameEditPart("+ element+")",channel);
		this.element = element;
		if ((GraphNode)graphnode.getSemanticParent()==null){
			Debug.error(this, "PortEditPart is not associated to a port", channel);
		}
		else{
			port=(org.eclipse.uml2.uml.Port)((Uml1SemanticModelBridge)((GraphNode)graphnode.getSemanticParent()).getSemanticModel()).getElement();
		}
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#getUmlElement()
	 */
	@Override
	public Port getUmlElement(){
		return port;
	} 

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#isElementImport()
	 */
	@Override
	public boolean isElementImport(){
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#getElementImport()
	 */
	@Override
	public ElementImport getElementImport(){
		return null;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#createFigure()
	 */
	@Override
	protected StringFigure createFigure() {
		return new StringFigure(this.getcompleteLabel());
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#activate()
	 */
	@Override
	public void activate() {
		if (isActive()) {
			Debug.debug(this, "should not activate an already active edit part", channel);
			return;
		}
		// start listening for changes in the model
		// FIXME RS bug to check this <=> _adapter
		((Notifier)getGraphNode()).eAdapters().add(_adapter);
		if (port != null){
			((Notifier)port).eAdapters().add(_adapter);
			if (port.getType() != null){
				((Notifier)(port.getType())).eAdapters().add(_adapter);
			}
		}
		super.activate();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#deactivate()
	 */
	@Override
	public void deactivate() {
		if (!isActive()) {
			Debug.debug(this, "should not deactivate an already deactived edit part", channel);
			return;
		}
		// stop listening for changes in the model
		// FIXME RS bug to check this <=> _adapter
		((Notifier)getGraphNode()).eAdapters().remove(_adapter);
		if (port!=null){
			((Notifier)port).eAdapters().remove(_adapter);
			if (port.getType()!=null){
				((Notifier)(port.getType())).eAdapters().remove(_adapter);
			}
		}
		super.deactivate();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.NodeNameDisplayEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals() {
		StringFigure f = (StringFigure) getFigure();
		Point p = getGraphNode().getPosition();
		com.cea.papyrus.umlutils.Property utilProperty = new com.cea.papyrus.umlutils.Property(port);

		int style = ICustomAppearence.DEFAULT_UML_PORT;
		// get properties on graph node for property: custom display
		String value = getProperty(ICustomAppearence.CUSTOM_APPEARENCE_KEY);

		if(value == null) {
			com.cea.papyrus.diagraminterchange2.di2.Property prop = Di2Factory.eINSTANCE.createProperty();
			getGraphNode().getProperty().add(prop);
			prop.setKey(ICustomAppearence.CUSTOM_APPEARENCE_KEY);
			value = ""+ICustomAppearence.DEFAULT_UML_PORT;
			prop.setValue(value);
		}
		if(value != null) {
			try {
				style = Integer.parseInt(value);
			} catch (NumberFormatException e) {
				Debug.log(e);
			}
		}

		/** Stereotype presentation */
		String stereotypePresentation = null;

		GraphNode semanticParent= (GraphNode)getGraphNode().getSemanticParent();
		if(semanticParent!=null){
			if(semanticParent.getSemanticModel() != null) {
				if(semanticParent.getSemanticModel().getPresentation() != null) {
					stereotypePresentation = semanticParent.getSemanticModel().getPresentation();
				} else {
					semanticParent.getSemanticModel().setPresentation(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION);
					stereotypePresentation = ModelerHelper.TEXT_STEREOTYPE_PRESENTATION;
				}
			}

			StringFigure fig = (StringFigure)getFigure();

			String stereotypes;
			stereotypes = horizontalStereotypesToDisplay();

			if((stereotypes!="")&& 
					((stereotypePresentation != null) && (stereotypePresentation.equals(ModelerHelper.TEXT_ICON_STEREOTYPE_PRESENTATION) || 
							stereotypePresentation.equals(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION)))){
				fig.setStereotypes(stereotypes);//add stereotypes on the operation figure
			}
			else {
				fig.setStereotypes(null);
			}
			String newText = utilProperty.getCustomLabel(style);
			f.setName(newText);

			Rectangle r = new Rectangle(p ,f.getPreferredSize());
			((GraphicalEditPart) getParent()).setLayoutConstraint(
					this,
					f,
					r);
		}	}

	/**
	 * Returns the label to display
	 * @return the label to display
	 */
	public String getLabel() {
		String type="<undefined>";
		if (port.getType()!=null){
			type=port.getType().getName();
		}

		return port.getName()+": "+type;
	}

	/**
	 * Returns the complete label
	 * @return the complete label
	 */
	public String getcompleteLabel() {
		String stereotypesToDisplay="";
		Iterator<Stereotype> iter= getUmlElement().getAppliedStereotypes().iterator();

		while(iter.hasNext()){
			Stereotype stereo = iter.next();
			stereotypesToDisplay = stereotypesToDisplay+stereo.getName()+", ";
		}

		if (!(stereotypesToDisplay.equals(""))) {
			stereotypesToDisplay = PapyrusPlugin.ST_LEFT+stereotypesToDisplay.substring(0, stereotypesToDisplay.length()-2)+PapyrusPlugin.ST_RIGHT+"\n";
		}

		return stereotypesToDisplay+ " "+getLabel();

	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#stereotypesToDisplay(java.lang.String)
	 */
	@Override
	public String stereotypesToDisplay(String separator) {
		EList displayStereotypesList = ((GraphNode)getGraphNode().getSemanticParent()).getProperty();
		Iterator<Property> iter = displayStereotypesList.iterator();
		String stereotypesToDisplay="";


		while(iter.hasNext()){
			Property prop = iter.next();
			// Bug correction: prop.getKey().equals(XXY) throws a NPE if getKey returns null 
			if(ModelerHelper.PROPERTY_STEREOTYPE_DISPLAY.equals(prop.getKey())){
				String qualifiedName = prop.getValue();

				// property value contains qualifiedName ==> extract name from it
				StringTokenizer strToken = new StringTokenizer(qualifiedName, "::");
				String name="";
				while(strToken.hasMoreTokens()) {
					name = strToken.nextToken();
				}

				stereotypesToDisplay = stereotypesToDisplay+name.substring(0, 1).toLowerCase()+name.substring(1, name.length())+","+separator;
			}
		}
		if (!(stereotypesToDisplay.equals(""))) {
			stereotypesToDisplay = stereotypesToDisplay.substring(0, stereotypesToDisplay.length()-2);
		}

		return stereotypesToDisplay;
	}

}